package com.deyuanyun.pic.settings.service.base.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.deyuanyun.pic.common.util.CommonUtil;
import com.deyuanyun.pic.common.util.ObjectUtil;
import com.deyuanyun.pic.common.util.StringUtils;
import com.deyuanyun.pic.common.util.web.Asserts;
import com.deyuanyun.pic.settings.controller.dto.BizMsgThresholdVO;
import com.deyuanyun.pic.settings.controller.dto.base.AcDcMiorRecordDTO;
import com.deyuanyun.pic.settings.controller.dto.base.ExinspCptestStationDTO;
import com.deyuanyun.pic.settings.controller.dto.base.PigTaskDTO;
import com.deyuanyun.pic.settings.controller.dto.base.PipeScheduleVO;
import com.deyuanyun.pic.settings.controller.dto.base.RepairTaskDTO;
import com.deyuanyun.pic.settings.controller.dto.base.RiskAssessmentDTO;
import com.deyuanyun.pic.settings.controller.dto.prvlg.RoleDTO;
import com.deyuanyun.pic.settings.domain.base.BizMsgThreshold;
import com.deyuanyun.pic.settings.domain.base.BizThreshold;
import com.deyuanyun.pic.settings.enumeration.ThresholdType;
import com.deyuanyun.pic.settings.mapper.base.BizMsgSendMapper;
import com.deyuanyun.pic.settings.mapper.base.BizMsgThresholdMapper;
import com.deyuanyun.pic.settings.mapper.base.CustomBizMsgThresholdMapper;
import com.deyuanyun.pic.settings.service.base.BizMsgThresholdService;
import com.deyuanyun.pic.settings.service.base.BizThresholdService;
import com.deyuanyun.pic.settings.service.msgtemplate.PipeCyclePushMsg;
import com.deyuanyun.pic.settings.support.utils.CronUtils;
import com.deyuanyun.pic.settings.task.PipeLineCycleTask;
import com.deyuanyun.pic.settings.task.QuartzConsts;
import com.deyuanyun.pic.settings.task.SchedulerJob;
import com.deyuanyun.pic.settings.task.util.QuartzManagerUtil;
import org.quartz.JobKey;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

@Service
public class BizMsgThresholdServiceImpl implements BizMsgThresholdService {

    private @Autowired BizMsgThresholdMapper bizMsgThresholdMapper;

    private @Autowired CustomBizMsgThresholdMapper customBizMsgThresholdMapper;

    private @Autowired BizMsgSendMapper bizMsgSendMapper;

    private @Autowired BizThresholdService bizThresholdService;

    private static final Logger logger = LoggerFactory.getLogger(BizMsgThresholdServiceImpl.class);

    public BizMsgThreshold selectByPrimaryKey(String id) {
        return this.bizMsgThresholdMapper.selectByPrimaryKey(id);
    }

    public int deleteByPrimaryKey(String id) {
        return this.bizMsgThresholdMapper.deleteByPrimaryKey(id);
    }

    public int updateByPrimaryKeySelective(BizMsgThreshold record) {
        return this.bizMsgThresholdMapper.updateByPrimaryKeySelective(record);
    }

    public int updateByPrimaryKey(BizMsgThreshold record) {
        return this.bizMsgThresholdMapper.updateByPrimaryKey(record);
    }

    public int insert(BizMsgThreshold record) {
        return this.bizMsgThresholdMapper.insert(record);
    }

    @Override
    public int insertSelective(BizMsgThreshold record) {
        return this.bizMsgThresholdMapper.insertSelective(record);
    }

    /**
     * 根据业务阀值类型删除信息
     * @param type
     * @param bizMsgThresholdId 新的业务阀值表id
     * @param bizThresholdId 新的业务阀值系统设置表id
     * @return
     */
    private void deleteByType(String type, String bizMsgThresholdId, String bizThresholdId) {
        BizMsgThresholdVO msgThresholdVO = customBizMsgThresholdMapper.queryDataByTypeOne(type);
        BizThreshold threshold = bizThresholdService.querySysByType(type);

        if(msgThresholdVO != null) {
            String id = msgThresholdVO.getId();
            if(StringUtils.isNotEmpty(id)) {
                customBizMsgThresholdMapper.deleteBizMsgByParentId(id); //先删除以前的

            }
        }
        if(threshold != null) {
            String id = threshold.getId();
            if(StringUtils.isNotEmpty(id)) {
               customBizMsgThresholdMapper.deleteSysBizMsgByParentId(id);//先删除以前的
            }
        }

        ThresholdType thresholdType = ThresholdType.getThresholdType(type);

        BizMsgThreshold bizMsgThreshold = new BizMsgThreshold();
        bizMsgThreshold.setName(thresholdType.getMsg());
        bizMsgThreshold.setShortName(thresholdType.getMsg());
        bizMsgThreshold.setType(thresholdType.getValue());
        bizMsgThreshold.setState((short) 0);
        bizMsgThreshold.setCreateDate(new Date());
        bizMsgThreshold.setId(bizMsgThresholdId);
        bizMsgThreshold.setLevel(Integer.valueOf(thresholdType.getLevel()).shortValue());
        bizMsgThresholdMapper.insertSelective(bizMsgThreshold); //重新初始化

        BizThreshold bizThreshold = new BizThreshold();
        bizThreshold.setIsSys((short) 1);
        BeanUtils.copyProperties(bizMsgThreshold, bizThreshold);
        bizThreshold.setId(bizThresholdId);
        bizThresholdService.insertSelective(bizThreshold);
    }

    @Override
    public boolean insertBizMsgThresholdInfo(List list, String type) {
        String bizMsgThresholdId = CommonUtil.getUUID();
        String bizThresholdId = CommonUtil.getUUID();
        deleteByType(type, bizMsgThresholdId, bizThresholdId); //先删除以前的

        for (int i = 0, len = list.size(); i <  len; i++) {
            BizMsgThreshold bizMsgThreshold = JSONObject.parseObject(list.get(i).toString(), BizMsgThreshold.class);
            bizMsgThreshold.setParentId(bizMsgThresholdId);
            bizMsgThreshold.setCreateDate(new Date());
            bizMsgThreshold.setId(CommonUtil.getUUID());
            bizMsgThreshold.setShortName(bizMsgThreshold.getName());
            bizMsgThreshold.setState((short) 0);
            insertSelective(bizMsgThreshold);

            BizThreshold bizThreshold = new BizThreshold();
            BeanUtils.copyProperties(bizMsgThreshold, bizThreshold);
            bizMsgThreshold.setId(CommonUtil.getUUID());
            bizThreshold.setParentId(bizThresholdId);
            bizThreshold.setIsSys((short) 1);
            bizThresholdService.insertSelective(bizThreshold);
        }
        return false;
    }

    @Override
    public BizMsgThresholdVO queryDataByTypeOne(String type) {
        return customBizMsgThresholdMapper.queryDataByTypeOne(type);
    }

    @Override
    public List<BizMsgThresholdVO> queryChildForPage(String type) {
        return customBizMsgThresholdMapper.queryChildForPage(type);
    }

    @Override
    public List<BizMsgThresholdVO> queryDataByTypes(String ... types) {
        return customBizMsgThresholdMapper.queryDataByTypes(types);
    }

    @Override
    public List<RoleDTO> queryAllRole() {
        return customBizMsgThresholdMapper.queryAllRole();
    }

    @Override
    public List<RiskAssessmentDTO> queryRiskAssessmentInfo(Map<String, Object> map) {
        return customBizMsgThresholdMapper.queryRiskAssessmentInfo(map);
    }

    /**
     * 根据业务阀值类型枚举数组对象，从jsonObject中取出来进行更新操作
     * @param updateThresholds
     * @param map
     * @return 
     * @author axiao(xj08.dream@gmail.com)
     * @date 2016-07-20
     */
    private void thresholdUpdateBizThreshold(ThresholdType[] updateThresholds, Map<String, Object> map) {
        ThresholdType thresholdType;
        for (int i = 0, len = updateThresholds.length; i < len; i++) {
            thresholdType = updateThresholds[i];
            Object thresholdObj = map.get(thresholdType.getValue());
            Asserts.assertTrue(!ObjectUtil.isEmptyAll(thresholdObj), thresholdType.getMsg() + "不能为空");
            if(logger.isInfoEnabled()) {
                logger.info("得到需要修改的类型：" + thresholdType.getValue() + ", 类型中文为：" +
                        thresholdType.getMsg() + ", 对应的菜单等级为：" + thresholdType.getLevel());
            }
            BizMsgThresholdVO bizMsgThresholdVO = JSONObject.parseObject(thresholdObj.toString(), BizMsgThresholdVO.class);
            updateBizMsgThresholdInfo(bizMsgThresholdVO);
        }
    }

    /**
     *  将自定义的业务阀值实体转换为业务阀值实体类
     *  @author axiao(xj08.dream@gmail.com)
     *  @date 2016-07-20
     *  @version 1.0
     *  Histroy: [修改人][时间][描述]
     */
    private void updateBizMsgThresholdInfo(BizMsgThresholdVO bizMsgThresholdVO) {
        if(!ObjectUtil.isEmptyAll(bizMsgThresholdVO)) {
            BizMsgThreshold bizMsgThreshold = new BizMsgThreshold();
            BeanUtils.copyProperties(bizMsgThresholdVO, bizMsgThreshold, "sort");
            if(bizMsgThresholdVO.getThresholdContentJson() != null) {
                bizMsgThreshold.setThresholdContent(JSON.toJSONString(bizMsgThresholdVO.getThresholdContentJson()));
            }
            bizMsgThreshold.setUpdateDate(new Date());
            bizMsgThresholdMapper.updateByPrimaryKeySelective(bizMsgThreshold);
        }
    }

    public void updatePipeSchedule(BizMsgThresholdVO oldBizMsgThreshold, BizMsgThresholdVO newBizMsgThreshold, String groupName) {
        if(oldBizMsgThreshold != null && newBizMsgThreshold != null) {
            if (logger.isInfoEnabled()) {
                logger.info("任务调度组名为：" + groupName);
            }
            String oldThresContent = oldBizMsgThreshold.getThresholdContent();

            String newThreContent = newBizMsgThreshold.getThresholdContent();

            if(StringUtils.isNotEmpty(oldThresContent) && StringUtils.isNotEmpty(newThreContent)) {
                List<PipeScheduleVO> oldScheduleVOs = JSONArray.parseArray(oldBizMsgThreshold.getThresholdContentJson().toString(), PipeScheduleVO.class);
                List<PipeScheduleVO> newScheduleVOs = JSONArray.parseArray(newBizMsgThreshold.getThresholdContentJson().toString(), PipeScheduleVO.class);

                Map<String, PipeScheduleVO> oldScheduleMap = new HashMap<String, PipeScheduleVO>();
                PipeScheduleVO scheduleVO;

                for (int i = 0, len = oldScheduleVOs.size(); i < len; i++) {
                    scheduleVO = oldScheduleVOs.get(i);
                    oldScheduleMap.put(scheduleVO.getPipeLineId() + scheduleVO.getBeginMileageId() + scheduleVO.getEndMileageId(), scheduleVO);
                }

                List<JobKey> startNowJobs = new ArrayList<JobKey>();

                //开始循环判断前台传过来的数据，并创建任务调度，并把需要删除的任务查询出来
                for (int i =0, len = newScheduleVOs.size(); i < len; i++) {
                    scheduleVO = newScheduleVOs.get(i);
                    String pipeLineId = scheduleVO.getPipeLineId();
                    String beginMileageId = scheduleVO.getBeginMileageId();
                    String endMileageId = scheduleVO.getEndMileageId();
                    String name = pipeLineId + beginMileageId + endMileageId;

                    if(oldScheduleMap.containsKey(name)) {//如果在保存之前的map中存在新的key，则从map中删除，不需要删除job，反之如果不包含的都是需要删除的任务
                        oldScheduleMap.remove(name);
                    }
                    if(pipeLineId != null && beginMileageId != null && endMileageId != null) {
                        if(logger.isInfoEnabled()) {
                            logger.info("正在准备创建或修改任务调度为：" + name + "，任务调度组名为：" + groupName +  "的任务调度");
                        }
                        Map<String, Object> jobdataMap = new HashMap<String, Object>();
                        jobdataMap.put(PipeCyclePushMsg.SCHEDULE_VO, scheduleVO);
                        jobdataMap.put(PipeCyclePushMsg.PIPE_SCHEDULE, newBizMsgThreshold);

                        SchedulerJob schedulerJob = new SchedulerJob(name, groupName, PipeLineCycleTask.class, CronUtils.pipeCronStr(scheduleVO), jobdataMap);
                        QuartzManagerUtil.addCronJob(schedulerJob);

                        if(scheduleVO.getStartDate().compareTo(new Date()) == -1) { //当设置的第一次执行时间小于当前时间的时候执行一次
                            startNowJobs.add(JobKey.jobKey(name, groupName));
                        }
                        if(logger.isInfoEnabled()) {
                            logger.info("任务调度为：" + name + "，任务调度组名为：" + groupName + "的任务调度创建或修改完毕");
                        }
                    }
                }
                List<JobKey> jobKeys = new ArrayList<JobKey>();
                Set<String> oldScheduleKeys = oldScheduleMap.keySet();
                for (String oldScheduleKey : oldScheduleKeys) {//循环遍历保存需要删除的任务
                    jobKeys.add(JobKey.jobKey(oldScheduleKey, groupName));
                }
                QuartzManagerUtil.removeJob(jobKeys);

                //立即运行任务
                QuartzManagerUtil.startJobNow(startNowJobs);
            }
        }
    }

    public void updateRisk(Map<String, Object> map) {
        ThresholdType updateThresoldArr[] = {ThresholdType.RISK_CORROSION_PERCENT, ThresholdType.RISK_IMMEDIATE_REPAIR, ThresholdType.RISK_MENACE_GEOLOGIC_HAZARD,
                ThresholdType.RISK_MENACE_MANUFACTURE_CONSTRUCTION, ThresholdType.RISK_MENACE_MISOPERATION, ThresholdType.RISK_MENACE_THIRD_PARTY_DAMAGE,
                ThresholdType.RISK_SYSTEM_SCHEDULE, ThresholdType.RISK_OVER_UNDER_PROTECTION, ThresholdType.RISK_AC_DC_INTERFERENCE};
        thresholdUpdateBizThreshold(updateThresoldArr, map);

        ThresholdType riskPipe = ThresholdType.RISK_PIPE_SCHEDULE;//风险评价管道周期枚举
        //风险评价周期任务调度
        Object pipeScheduleObj = map.get(riskPipe.getValue());
        Asserts.assertTrue(!ObjectUtil.isEmptyAll(pipeScheduleObj), "风险评价周期信息不能为空");
        if(pipeScheduleObj != null) {
            BizMsgThresholdVO pipeScheduleThreshold = JSONObject.parseObject(pipeScheduleObj.toString(), BizMsgThresholdVO.class);//前台传的管道周期阀值信息
            Object thresholdObj = pipeScheduleThreshold.getThresholdContentJson();
            Asserts.assertTrue(thresholdObj != null, "风险评价周期信息不能为空");
            BizMsgThresholdVO oldBizMsgThreshold = customBizMsgThresholdMapper.queryDataByTypeOne(riskPipe.getValue());//未修改之前的管道周期阀值信息
            updateBizMsgThresholdInfo(pipeScheduleThreshold);//持久化页面更改的管道数据
            pipeScheduleThreshold = customBizMsgThresholdMapper.queryDataByTypeOne(riskPipe.getValue());//保存之后重新获取一次
            updatePipeSchedule(oldBizMsgThreshold, pipeScheduleThreshold, QuartzConsts.RISK_PIPE_TASK_GROUP_NAME);
        }
    }

    @Override
    public void updateIntegrity(Map<String, Object> map) {
        ThresholdType[] updateThresoldArr = {ThresholdType.INTERNAL_INSP_APPRAISE, ThresholdType.INTERNAL_INSP_DEFECT_NOTICE_SCHEDULE,
                ThresholdType.INTERNAL_INSP_INSIDE_METAL_LOSS, ThresholdType.INTERNAL_INSP_OUTSIDE_METAL_LOSS, ThresholdType.INTERNAL_CATHODIC_PROTECTION_INPUT,
                ThresholdType.INTERNAL_POTENTIAL_INPUT, ThresholdType.INTERNAL_AC_CURRENT_DENSITY_INPUT, ThresholdType.INTERNAL_DC_CURRENT_DENSITY_INPUT,
                ThresholdType.INTERNAL_INSULATION_JOINT_INPUT, ThresholdType.INTERNAL_SACRIFICIAL_ANODE_INPUT, ThresholdType.INTERNAL_PROTECTING_COATING_INPUT, ThresholdType.INTERNAL_PROTECTING_COATING_ADVISE_INPUT};
        thresholdUpdateBizThreshold(updateThresoldArr, map);

        // 内检测周期任务调度
        ThresholdType inspPipe = ThresholdType.INTERNAL_INSP_PIPE_SCHEDULE;//完整性评价-内检测管道周期枚举
        Object inspPipeObj = map.get(inspPipe.getValue());
        Asserts.assertTrue(!ObjectUtil.isEmptyAll(inspPipeObj), inspPipe.getMsg() + "不能为空");
        if(inspPipeObj != null) {
            BizMsgThresholdVO inspPipeThre = JSONObject.parseObject(inspPipeObj.toString(), BizMsgThresholdVO.class);//前台传的管道周期阀值信息
            BizMsgThresholdVO oldBizMsgThreshold = customBizMsgThresholdMapper.queryDataByTypeOne(inspPipe.getValue());//未修改之前的管道周期阀值信息
            updateBizMsgThresholdInfo(inspPipeThre);//持久化页面更改的管道数据
            inspPipeThre = customBizMsgThresholdMapper.queryDataByTypeOne(inspPipe.getValue());//保存之后重新获取一次
            updatePipeSchedule(oldBizMsgThreshold, inspPipeThre, QuartzConsts.INSP_TASK_GOURP_NAME);
        }

        // 外检测周期任务调度
        ThresholdType extePipe = ThresholdType.INTERNAL_EXTE_PIPE_SCHEDULE;//完整性评价-内检测管道周期枚举
        Object extePipeObj = map.get(extePipe.getValue());
        Asserts.assertTrue(!ObjectUtil.isEmptyAll(extePipeObj), extePipe.getMsg() + "不能为空");
        if(extePipeObj != null) {
            BizMsgThresholdVO extePipeThre = JSONObject.parseObject(extePipeObj.toString(), BizMsgThresholdVO.class);//前台传的管道周期阀值信息
            BizMsgThresholdVO oldBizMsgThreshold = customBizMsgThresholdMapper.queryDataByTypeOne(extePipe.getValue());//未修改之前的管道周期阀值信息
            updateBizMsgThresholdInfo(extePipeThre);//持久化页面更改的管道数据
            extePipeThre = customBizMsgThresholdMapper.queryDataByTypeOne(inspPipe.getValue());//保存之后重新获取一次
            updatePipeSchedule(oldBizMsgThreshold, extePipeThre, QuartzConsts.EXTE_TASK_GOURP_NAME);
        }
    }

    @Override
    public void updateDefectEvaluation(Map<String, Object> map) {
        ThresholdType[] updateThresoldArr = {ThresholdType.DEFECT_IMMEDIATE_REPAIR, ThresholdType.DEFECT_METAL_LOSS,
                ThresholdType.DEFECT_PIT,
                ThresholdType.DEFECT_GIRTH_WELD, ThresholdType.DEFECT_REPAIR_TASKS};
        thresholdUpdateBizThreshold(updateThresoldArr, map);
    }

    @Override
    public int updateThresholdPageCancel(String type) {
        BizThreshold bizThreshold = bizThresholdService.querySysByType(type); //得到系统默认的业务阀值最上层的信息
        if(bizThreshold != null) {
            String id = bizThreshold.getId();
            if(!StringUtils.isEmpty(id)) {
                return bizThresholdService.updateSystemChildInfo(id);//根据父类id恢复下面对应子节点的默认设置
            }
        }
        return 0;
    }

    @Override
    public int updateThresPipePageCancel(String parentType, ThresholdType thresholdType, final String groupName) {
        BizMsgThresholdVO updateBefore = customBizMsgThresholdMapper.queryDataByTypeOne(thresholdType.getValue());//先得到恢复默认之前的管道周期任务信息
        String thresholdContent = updateBefore.getThresholdContent();//得到恢复默认之前的阀值信息

        BizThreshold bizThreshold = bizThresholdService.querySysByType(parentType); //得到系统默认的业务阀值最上层的信息
        if (bizThreshold != null) {
            String id = bizThreshold.getId();
            if (!StringUtils.isEmpty(id)) {
                int i = bizThresholdService.updateSystemChildInfo(id);//根据父类id恢复下面对应子节点的默认设置
                BizMsgThresholdVO updateAfter = customBizMsgThresholdMapper.queryDataByTypeOne(thresholdType.getValue());//得到恢复默认之后的管道周期任务信息
                updatePipeSchedule(updateBefore, updateAfter, groupName); //停用以前的任务调度，并创建默认新的任务
                return i;
            }
        }
        return 0;
    }

    @Override
    public boolean countRiskDefectMsg(Map<String, Object> paramMap) {
        int count = customBizMsgThresholdMapper.countRiskDefectMsg(paramMap);
        return count != 0;
    }

    @Override
    public boolean countPipeSchedule(Map<String, Object> paramMap) {
        int count = customBizMsgThresholdMapper.countPipeSchedule(paramMap);
        return count != 0;
    }

    @Override
    public Map<String, Object> findEvaluationTaskInfo(String taskId) {
        return customBizMsgThresholdMapper.findEvaluationTaskInfo(taskId);
    }

    @Override
    public List<RepairTaskDTO> queryRepairByIds(String... repairIds) {
        return customBizMsgThresholdMapper.queryRepairByIds(repairIds);
    }

    @Override
    public PigTaskDTO findPigTaskById(String taskId) {
        return customBizMsgThresholdMapper.findPigTaskById(taskId);
    }

    @Override
    public List<ExinspCptestStationDTO> queryRiskExinspCptestStation(String pipeLineId, Long beginMileage, Long endMileage) {
        return customBizMsgThresholdMapper.queryRiskExinspCptestStation(pipeLineId, beginMileage, endMileage);
    }

    @Override
    public List<AcDcMiorRecordDTO> queryRiskAcDcMiorInfo(String pipeLineId, Long beginMileage, Long endMileage) {
        return customBizMsgThresholdMapper.queryRiskAcDcMiorInfo(pipeLineId, beginMileage, endMileage);
    }

    @Override
    public Set<String> queryUseIdByRoleIds(Collection<String> roleIds) {
        return customBizMsgThresholdMapper.queryUseIdByRoleIds(roleIds);
    }
}